/*
 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <aos/aos.h>
#include <aos/kernel.h>

#include <aos/hal/i2c.h>
#include <ulog/ulog.h>
#include <yoc/atserver.h>
#include <pin_name.h>
#include "pin_config.h"

#ifdef TEST_IIC
#define DEVICE_ZERO               0x0
#define DEVICE_ONE                0x1

#define I2C_BUF_SIZE   32
#define I2C_TX_TIMEOUT 1000
#define I2C_RX_TIMEOUT 3000
#define I2C_TX_TIMEOUT_2 HAL_WAIT_FOREVER
#define I2C_RX_TIMEOUT_2 HAL_WAIT_FOREVER

// #define I2C_DEV_ADDR       0x40

/* define dev */
i2c_dev_t i2c0,i2c_dev0;
/* data buffer */
uint8_t i2c_data_buf_2[I2C_BUF_SIZE] = {0};
uint8_t i2c_data_buf1_2[I2C_BUF_SIZE] = {0};

void hal_iic_mem_2(int size,int tx_timeout,int rx_timeout)
{
    int ret     = -1;
    int i       = 0;

    /* i2c port set */
    i2c0.port = I2C_PORT_NUM;

    /* i2c attr config */
    i2c0.config.dev_addr = CK_IIC_SLAVE_ADDR;
    i2c0.config.freq = 100000;
    i2c0.config.address_width = I2C_HAL_ADDRESS_WIDTH_7BIT;
    i2c0.config.mode = I2C_MODE_MASTER;


    /* init i2c with the given settings */
    ret = hal_i2c_init(&i2c0);

    if (ret != 0) {
        printf("i2c0 init error !\n");
        hal_i2c_finalize(&i2c0);
        AT_BACK_ERR();
        return;
    }

    /* init the tx buffer */
    for (int i = 0; i < size; i++) {
        i2c_data_buf_2[i] = i;
    }

    hal_i2c_mem_write(&i2c0, CK_IIC_SLAVE_ADDR, EEPROM_PAGE_ADDR, I2C_MEM_ADDR_SIZE_16BIT, i2c_data_buf_2, size, tx_timeout);
    ret = hal_i2c_mem_read(&i2c0, CK_IIC_SLAVE_ADDR, EEPROM_PAGE_ADDR, I2C_MEM_ADDR_SIZE_16BIT, i2c_data_buf1_2, size, rx_timeout);
    if (ret == 0) {
        printf("i2c0 data received succeed !\n");
    } else {
        hal_i2c_finalize(&i2c0);
        AT_BACK_ERR();
        return;
    }
    for (i = 0; i < size; i++) {
        printf("%x,%x \t", i2c_data_buf_2[i], i2c_data_buf1_2[i]);

        if (((i + 3) % 4) == 0) {
            printf("\n");
        }
        if (i2c_data_buf_2[i]!=i2c_data_buf1_2[i]) {
            hal_i2c_finalize(&i2c0);
            AT_BACK_ERR();
            return;
        }
    }

    AT_BACK_OK(); 
    hal_i2c_finalize(&i2c0);
}


void hal_iic_api_2(void)
{
    int ret     = -1;

    /* i2c port set */
    i2c0.port = I2C_PORT_NUM;

    /* i2c attr config */
    i2c0.config.mode          = I2C_MODE_MASTER;
    i2c0.config.freq          = 100000;
    i2c0.config.address_width = I2C_HAL_ADDRESS_WIDTH_7BIT;
    i2c0.config.dev_addr      = I2C_DEV_ADDR;

    /* init i2c with the given settings */
    ret = hal_i2c_init(NULL);

    if (ret == 0) {
        AT_BACK_ERR();
    }

    AT_BACK_OK(); 
}

void hal_iic_eeprom_2(int freq,int width,int size,int tx_timeout,int rx_timeout)
{
    // write or read: ADDRHIGH ADDRLOW 
    uint8_t write_data[I2C_BUF_SIZE + 2] = {0x00, 0x20, 0};
    uint8_t read_data[I2C_BUF_SIZE + 2] = {0x00, 0x20, 0};
    uint8_t i = 0;
    int32_t ret;

    /* i2c port set */
    i2c_dev0.port = I2C_PORT_NUM;

    /* i2c attr config */
    i2c_dev0.config.mode          = I2C_MODE_MASTER;
    i2c_dev0.config.freq          = freq;
    i2c_dev0.config.address_width = width;
    i2c_dev0.config.dev_addr      = CK_IIC_SLAVE_ADDR;

    for (i = 2; i < size + 2; i++) {
        write_data[i] = i + 2;
    }

    ret = hal_i2c_init(&i2c_dev0);
    if (ret != 0) {
        printf("hal_i2c_init dev0 error\n");
        AT_BACK_ERR();
        return;
    }
    else{
        printf("hal_i2c_init dev0 succeed\n");
    }

    ret = hal_i2c_master_send(&i2c_dev0, CK_IIC_SLAVE_ADDR, write_data, size + 2, tx_timeout);
    if (ret != 0) {
        printf("hal_i2c_master_send1 error\n");
        AT_BACK_ERR();
        return;
    }
    aos_msleep(100);
    ret = hal_i2c_master_send(&i2c_dev0, CK_IIC_SLAVE_ADDR, read_data, 2, tx_timeout);
    if (ret != 0) {
        printf("hal_i2c_master_send2 error\n");
        AT_BACK_ERR();
        return;
    }

    ret = hal_i2c_master_recv(&i2c_dev0, CK_IIC_SLAVE_ADDR, read_data + 2, size, rx_timeout);
    if (ret != 0) {
        printf("hal_i2c_master_recv error\n");
        AT_BACK_ERR();
        return;
    }

    printf("write_data0,read_data0:\n");
    for (i = 0; i < size + 2; i++) {
        printf("%x,%x \t\n", write_data[i], read_data[i]);
        if (write_data[i] != read_data[i]) {
            printf("\ntest at24c64 dev0 write and read failed\n");
            AT_BACK_ERR();
            return;
        }
    }

    ret = hal_i2c_finalize(&i2c_dev0);
    if (ret != 0) {
        printf("hal_i2c_finalize error\n");
        AT_BACK_ERR();
        return;
    }

    printf("test_iic_eeprom successfully\n");
    AT_BACK_OK();
}

void test_hal_iic_eeprom(char *cmd, int type, char *data)
{
    drv_pinmux_config(PIN_IIC_SDA, PIN_IIC_SDA_FUNC_NO_SLAVE);
    drv_pinmux_config(PIN_IIC_SCL, PIN_IIC_SCL_FUNC_NO_SLAVE);
    
    if (strcmp((const char *)data, "'freq=100K'\0") == 0) {
        hal_iic_eeprom_2(100000,I2C_HAL_ADDRESS_WIDTH_7BIT,16,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'freq=400K'\0") == 0) {
        hal_iic_eeprom_2(400000,I2C_HAL_ADDRESS_WIDTH_7BIT,16,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'freq=3.4M'\0") == 0) {
        hal_iic_eeprom_2(3400000,I2C_HAL_ADDRESS_WIDTH_7BIT,16,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'width=7bit'\0") == 0) {
        hal_iic_eeprom_2(100000,I2C_HAL_ADDRESS_WIDTH_7BIT,16,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'width=10bit'\0") == 0) {
        hal_iic_eeprom_2(100000,I2C_HAL_ADDRESS_WIDTH_10BIT,16,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'size=1'\0") == 0) {
        hal_iic_eeprom_2(100000,I2C_HAL_ADDRESS_WIDTH_7BIT,1,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'size=32'\0") == 0) {
        hal_iic_eeprom_2(100000,I2C_HAL_ADDRESS_WIDTH_7BIT,32,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'recv_size=1'\0") == 0) {
        hal_iic_eeprom_2(100000,I2C_HAL_ADDRESS_WIDTH_7BIT,1,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'recv'\0") == 0) {
        hal_iic_eeprom_2(100000,I2C_HAL_ADDRESS_WIDTH_7BIT,16,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'API'\0") == 0) {
        hal_iic_api_2();
    } else if (strcmp((const char *)data, "'MEM_SIZE=16'\0") == 0) {
        hal_iic_mem_2(16,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'MEM_SIZE=1'\0") == 0) {
        hal_iic_mem_2(1,I2C_TX_TIMEOUT,I2C_RX_TIMEOUT);
    } else if (strcmp((const char *)data, "'MEM_TIMEOUT_FOREVER'\0") == 0) {
        hal_iic_mem_2(16,I2C_TX_TIMEOUT_2,I2C_RX_TIMEOUT_2);
    } else if (strcmp((const char *)data, "'TIMEOUT_FOREVER'\0") == 0) {
        hal_iic_eeprom_2(100000,I2C_HAL_ADDRESS_WIDTH_7BIT,16,I2C_TX_TIMEOUT_2,I2C_RX_TIMEOUT_2);
    }
}

#endif